#ifndef ACCESS_POINT_H_
#define ACCESS_POINT_H_
 
#include <iostream>
#include <string>
#include "cmd.h"


class AccessPoint 
{
  std::string int_to_str(int i)
    {
      char buff[80];
      sprintf(buff,"%d",i);
      std::string tmp(buff);
      return tmp;
    }

 public:

  AccessPoint()
    :  __essid(),         __address(),             __mode(),        
    __channel(),          __freq(),                __quality(), 
    __signal_lvl(),       __noise_lvl(),           __key(),
    __secure(false),      __has_essid(false),      __has_address(false),  
    __has_mode(false),    __has_channel(false),    __has_freq(false),
    __has_quality(false), __has_signal_lvl(false), __has_noise_lvl(false),
    __has_key(false),     __has_secure(false)
    {} 
  
  virtual void parse_scan_line(std::string str)
    {
      const int buff_len=132;
      char buff[buff_len];
      unsigned i;
   
      if( (i=str.find("Address:"))!=std::string::npos)
	{
	  std::string address;
	  address =str;
	  set_address(address);  
	}
      
      strncpy(buff,str.c_str(),buff_len);
      char *ptr1=strtok(buff,":");
      if(ptr1!=NULL)
	{
	  char *ptr2=strtok(NULL,":");
	  if(strcasestr(ptr1,"ESSID")!=NULL)
	    {
	      char *ptr3=strtok(ptr2,"\"");
	      // std::cout << "ESSID?: " << ptr3 << std::endl;
	      set_essid(ptr3);
	    } 
	  if(strcasestr(ptr1,"Mode")!=NULL)
	    {
	      set_mode(ptr2);
	    }
	  if(strcasestr(ptr1,"Channel")!=NULL)
	    {
	      int chan;
	      sscanf(ptr2,"%d",&chan);
	      set_channel(chan);
	    }
	  if(strcasestr(ptr1,"Frequency")!=NULL)
	    {
	      float freq;
	      sscanf(ptr2,"%f",&freq);
	      set_freq(freq);
	    }
	  if(strcasestr(ptr1,"key")!=NULL)
	    {
	      if(strstr(ptr2,"on"))
		set_secure();
	      else
		set_unsecure();
	    }
	  else
	    {
	      if((ptr1=strtok(buff,"="))!=NULL)
		{
		  if(strcasestr(ptr1,"Quality")!=NULL)
		    {
		      int qual;
		      ptr2=strtok(NULL,"/");
		      sscanf(ptr2,"%d",&qual);
		      set_quality(qual);
		    }
		}
	    }
	}
    }

  std::string get_essid()
    {
      return __essid;
    }
  std ::string get_address()
    {  
      return __address;
    } 
  std::string get_mode()
    { 
      return __mode;
    } 
  int get_channel()
    {
      return __channel;
    }
  float get_freq()
    {
      return __freq;
    }
  int get_quality()
    {
      return __quality;
    }
  int get_signal_lvl()
    {
      return __signal_lvl;
    }
  int get_noise_lvl()
    {
      return __noise_lvl;
  }
  bool is_secure()
    {
      return __secure;
    }
  
  std::string get_key()
    {
      return __key;
    }
  
  void set_essid(std::string essid)
    {
      __has_essid=true;
      __essid=essid;
    }
  void set_address(std::string address)
    {
      __has_address=true;
      __address=address;
    }
  void set_mode(std::string mode)
    {
      __has_mode=true;
      __mode=mode;
    }
  void set_channel(int channel)
    {
      __has_channel=true;
      __channel=channel;
    }
  void set_freq(float freq)
    {
      __has_freq=true;
      __freq=freq;
    }
  void set_quality(int quality)
    {
      __has_quality=true;
      __quality=quality;
    }
  void set_signal_lvl(int signal_lvl)
    {
      __has_signal_lvl=true;
      __signal_lvl=signal_lvl;
    }
  void set_noise_lvl(int noise_lvl)
    {
      __has_noise_lvl=true;
      __noise_lvl=noise_lvl;
    }

  void set_secure()
    {
      __has_secure=true;
      __secure=true;
    }

  void set_unsecure()
    {
      __has_secure=true;
      __secure=false;
    }

  void set_key(std::string key)
    {
      __has_key=true;
      __key=key;
    }
  
  bool has_essid()
    {
      return __has_essid;
    }
  bool has_address()
    {
      return __has_address;
    }
  bool has_mode()
    {
      return __has_mode;
    }
  bool has_channel()
    {
      return __has_channel;
    }
  bool has_freq()
    {
      return __has_freq;
    }
  bool has_quality()
    {
      return __has_quality;
    }
  bool has_signal_lvl()
    {
      return __has_signal_lvl;
    }
  bool has_noise_lvl()
    {
      return __has_noise_lvl;
    }
  bool has_key()
    {
    return __has_key;
    }
  bool has_secure()
    {
    return __has_secure;
    }
  
  void print()
    {      
      if(has_essid())
	std::cout << "essid:      "    << get_essid() << std::endl;
      if(has_address())
	std::cout << "address:    " << get_address() << std::endl;
      if(has_mode())
      std::cout << "mode:       "    << get_mode() << std::endl;
      if(has_channel())
	std::cout << "channel:    " << get_channel() << std::endl;
      if(has_freq())
	std::cout << "freq:       "    << get_freq() << std::endl;
      if(has_quality())
	std::cout << "quality:    " << get_quality() << std::endl;
      if(has_signal_lvl())
	std::cout << "signal_lvl: " << get_signal_lvl() << std::endl;
      if(has_noise_lvl())
	std::cout << "noise_lvl:  " << get_noise_lvl() << std::endl; 
      if(has_key())
      std::cout << "key:        " << get_key() << std::endl; 
      if(has_secure())
	{
	  if(is_secure())
	    std::cout << "SECURE"  << std::endl; 
	  else
	    std::cout << "UNSECURE"  << std::endl; 
	}
    }
  void print_line()
    {      
      if(has_essid())
	std::cout << "essid: "  << get_essid(); 
      if(has_mode())
	std::cout << "  mode: "      << get_mode();
      if(has_channel())
	std::cout << "  channel: " << get_channel();
      if(has_quality())
	std::cout << "  quality:    " << get_quality() << "/100";
      if(has_secure())
	{
	  if(is_secure())
	    std::cout << "   SECURE" ; 
	  else
	    std::cout << "  UNSECURED" ; 
	}
      std::cout << std::endl; 
    }

 bool connect(std::string adaptor)
  {
      // ap is 
	  if (is_secure())
	    {
	      std::cerr << "Sorry.  Network is Secure"  << std::endl;
	      std::cerr << "Not Supported. (yet)" << std::endl;
	      std::cerr << "Exiting..." << std::endl;
	      
	      return 0;
	    }
		
	  std::string chan_str="channel " + int_to_str(get_channel()) 
	    +" key off";
	  std::cout << "Connecting... " << std::endl;
	  Cmd config("iwconfig", adaptor,"mode managed essid",get_essid(),
		     chan_str);
	  config.echo();
	  config.exec();
	  
	  return true;
  }


 virtual ~AccessPoint()
   {}
  
 private:
  std::string __essid;
  std::string __address;
  std::string __mode;
  int __channel;
  float __freq;
  int __quality;
  int __signal_lvl;
  int __noise_lvl;
  std::string __key;
  bool __secure;

  bool  __has_essid;
  bool __has_address;
  bool __has_mode;
  bool __has_channel;
  bool __has_freq;
  bool __has_quality;
  bool __has_signal_lvl;
  bool __has_noise_lvl;
  bool __has_key;
  bool __has_secure;
};

class Channel
{
 public:
  Channel(int channel, double freq)
    : __channel(channel), __freq(freq)
  {}
 
  void print()
  {
    std::cout << "Channel " << get_channel() 
	      << " : "      << get_freq() << " G?Hz" 
	      << std::endl;
  }
  //  set channel(int chan)
  // {
  //  __channel=chan;
  //
  // }
  
  virtual int get_channel()
  { return __channel; }
  virtual double get_freq()
  { return __freq; }
  
virtual ~Channel()
  {}
 private:
 int __channel;
 double __freq;
 
  double channel_to_freq(int channel)
  {
    switch(channel)
      {
      case 1 : 
	__freq=2.412;
	break;
      case 2 : 
	__freq=2.417;
	break;
      case 3 :
	__freq=2.422;
	break;
      case 4 : 
	__freq=2.427;
	break;
      case 5 : 
	__freq=2.432;
	break;
      case 6 : 
	__freq=2.437;
	break;
      case 7 : 
	__freq=2.442;
	break;
      case 8 : 
	__freq=2.447;
	break;
      case 9 : 
	__freq=2.452;
	break;
      case 10 : 
	__freq=2.457;
	break;
      case 11 : 
	__freq=2.462;
	break;
      case 36 : 
	__freq=5.18;
	break;
      case 40 : 
	__freq=5.2;
	break;
      case 44 : 
	__freq=5.22;
	break;
      case 48 : 
	__freq=5.24;
	break;
      case 52 : 
	__freq=5.26;
	break;
      case 56 : 
	__freq=5.28;
	break;
      case 60 : 
	__freq=5.3;
	break;
      case 64 : 
	__freq=5.32;
	break;
      case 149 : 
	__freq=5.745;
	break;
      case 153 : 
	__freq=5.765;
	break;
      case 157 : 
	__freq=5.785;
	break;
      case 161 : 
	__freq=5.805;
	break;
      case 165 : 
	__freq=5.825;
	break;
      }
    return __freq;
  }
};

class Channel1 : public Channel
{
 public:
 Channel1() : Channel(1 ,2.412)
    {}
};

class Channel2 : public Channel
{
 public:
 Channel2() : Channel(2, 2.417)
    {}
};

class Channel3 : public Channel
{
 public:
 Channel3() : Channel(3, 2.422)
    {}
};

class Channel4 : public Channel
{
 public:
 Channel4() : Channel(4, 2.427)
    {}
};

class Channel5 : public Channel
{
 public:
 Channel5() : Channel(5, 2.432)
    {}
};

class Channel6 : public Channel
{
 public:
 Channel6() : Channel(6, 2.437)
    {}
};

class Channel7 : public Channel
{
 public:
 Channel7() : Channel(7, 2.442)
    {}
};

class Channel8 : public Channel
{
 public:
 Channel8() : Channel(8, 2.447)
    {}
};

class Channel9 : public Channel
{
 public:
 Channel9() : Channel(9, 2.452)
    {}
};

class Channel10 : public Channel
{
 public:
 Channel10() : Channel(1, 2.457)
    {}
};

class Channel11 : public Channel
{
 public:
 Channel11() : Channel(11, 2.462)
    {}
};

class Channel36 : public Channel
{
 public:
 Channel36() : Channel(36, 5.18)
    {}
};

class Channel40 : public Channel
{
 public:
 Channel40() : Channel(40, 5.2)
    {}
};

class Channel44 : public Channel
{
 public:
 Channel44() : Channel(44, 5.22)
    {}
};

class Channel48 : public Channel
{
 public:
 Channel48() : Channel(48, 5.24)
    {}
};

class Channel52 : public Channel
{
 public:
 Channel52() : Channel(52, 5.26)
    {}
};

class Channel56 : public Channel
{
 public:
 Channel56() : Channel(58, 5.28)
    {}
};

class Channel60 : public Channel
{
 public:
 Channel60() : Channel(60, 5.3)
    {}
};

class Channel64 : public Channel
{
 public:
 Channel64() : Channel(64, 5.32)
    {}
};

class Channel149 : public Channel
{
 public:
 Channel149() : Channel(149, 5.745)
    {}
};

class Channel153 : public Channel
{
 public:
 Channel153() : Channel(153, 5.765)
    {}
};

class Channel157 : public Channel
{
 public:
 Channel157() : Channel(157, 5.785)
    {}
};

class Channel161 : public Channel
{
 public:
 Channel161() : Channel(161, 5.805)
    {}
};

class Channel165 : public Channel
{
 public:
 Channel165() : Channel(165, 5.825)
    {}
};

#endif



